EcoSystem|Graphql-binding

🔗 graphql-binding 可以在 graphql server 中嵌入grahql API
核心概念是通过为 GraphQL API 创建一个对象,表现出 API 的功能. 这个对象暴露的方法和GraphQL API schema 中定义的查询方法是镜像关系.

Install

1
yarn add graphql-binding

API

constructor

1
constructor(options: BindingOptions): Binding
Key Required Type Default Note
schema Yes GraphQLSchema - The executable GraphQL schema for binding
fragmentReplacements No FragmentReplacements {} A list of GraphQL fragment definitions, specifying fields that are required for the resolver to function correctly
before No () => void (() => undefined) A function that will be executed before a query/mutation is sent to the GraphQL API
handler No any null The handler object from JS Proxy
subscriptionHandler No any null

query&mutation

1
2
binding.query.<rootField>: QueryMap<any> // where <rootField> is the name of a field on the Query type in the mapped GraphQL schema
binding.mutation.<rootField>: QueryMap<any> // where <rootField> is the name of a field on the Mutation type in the mapped GraphQL schema

binding对象暴露出两个接口 query,mutate可以用于执行操作.分别接收三个参数

实例

假设有下面的 schema

1
2
3
4
5
6
7
type Query {
user(id: ID!): User
}

type Mutation {
createUser(): User!
}
1
2
binding.query.user({ id: 'abc' })
binding.mutation.createUser()
1
2
3
4
5
6
7
findUser(parent, args, context, info) {
return binding.user({ id: args.id }, context, info)
}

newUser(parent, args, context, info) {
return binding.createUser({}, context, info)
}
subscription
1
2
3
binding.subscription.<rootField>(...):  AsyncIterator<any> | Promise<AsyncIterator<any>> 
// where <rootField> is the name of a field
//on the Subscription type in the mapped GraphQL schema

简单实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const { makeExecutableSchema } = require('graphql-tools')
const { Binding } = require('graphql-binding')

const users = [
{
name: 'Alice',
},
{
name: 'Bob',
},
]

const typeDefs = `
type Query {
findUser(name: String!): User
}
type User {
name: String!
}
`

const resolvers = {
Query: {
findUser: (parent, { name }) => users.find(u => u.name === name),
},
}

const schema = makeExecutableSchema({ typeDefs, resolvers })

const findUserBinding = new Binding({
schema,
})

findUserBinding.findUser({ name: 'Bob' })
.then(result => console.log(result))

与 Prisma 的联系

graphcool-binding(prisma) 是这个版本的实现方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Instantiate `Prisma` based on concrete service
const prisma = new Prisma({
typeDefs: 'schemas/database.graphql',
endpoint: 'https://us1.prisma.sh/demo/my-service/dev'
secret: 'my-super-secret-secret'
})

// Retrieve `name` of a specific user
prisma.query.user({ where { id: 'abc' } }, '{ name }')

// Retrieve `id` and `name` of all users
prisma.query.users(null, '{ id name }')

// Create new user called `Sarah` and retrieve the `id`
prisma.mutation.createUser({ data: { name: 'Sarah' } }, '{ id }')

// Update name of a specific user and retrieve the `id`
prisma.mutation.updateUser({ where: { id: 'abc' }, data: { name: 'Sarah' } }, '{ id }')

// Delete a specific user and retrieve the `name`
prisma.mutation.deleteUser({ where: { id: 'abc' } }, '{ id }')

内部机制

prisma 的函数调用最终翻译为 graphql-binding 的方式

1
2
3
4
5
6
prisma.exists.Post({
id: 'abc',
author: {
name: 'Sarah'
}
})